/*
模块功能为：将轮询RAM2和RAM1，每一次轮询到某个地址，就会让RAM2的令牌数加上RAM1中每次增加的数量（但是RAM1数据格式中有上限规定）
*/


`include    "top_define.v"
// `define     TIMEDELAY            1  

module input_token(rst_n       ,
                   clk         ,
                   cpu_fread_write ,
                   cpu_faddr   ,
                   q_a_1       , //RAM1输出内容
                   q_a_2       , //RAM2输出内容
                   wren_a_2    , //给到RAM2
                   data_a_2    , //给到两个RAM（给到RAM1只有在“初始化”时才有）
                   address_a   , //给到两个RAM（需要轮询读出内容）
				   busy        , //由flow_ctrl_emac给到，表示正在查找
				   operate_addr, //由flow_ctrl_emac给到，表示正在对指定的地址操作
                   flow_ram1_wren, //给到RAM1写使能（step==5时为wren_a_2，即表示在进行：“表项清空”操作！，除此之外没有任何操作，注意要延后RAM2一拍！）
                   
                    ram1_cena ,
                    ram2_cena
                   );
           
input            rst_n           ;
input            clk             ;
input            cpu_fread_write ;
input [7:0]      cpu_faddr       ;
input [31:0]     q_a_1           ;
input [31:0]     q_a_2           ;
output           wren_a_2        ;
output[31:0]     data_a_2        ;
output[7 :0]     address_a       ;

input            busy            ;
input [7 :0]     operate_addr    ;

reg             wren_a_2         ;
reg   [31:0]    data_a_2         ;
reg   [7 :0]    address_a        ;

reg   [8:0]     loop             ;
reg   [2:0]     step             ;
    //状态机：
    //3'd5表示初始化RAM1和RAM2
    //3'd0等待没有查找当前的地址
    //3'd1等待读出
    //3'd2等待读出
    //3'd3将增加令牌数
    //3'd4等待没有查找当前的地址

output reg flow_ram1_wren;
output reg ram1_cena ;
output reg ram2_cena ;

//**************************************************************
//写入RAM1使能
always @ (posedge clk or negedge rst_n)
    begin
        if(!rst_n)
        flow_ram1_wren <= 1'b0; 
        else if(step==3'd5 )
        flow_ram1_wren <= 1'b1; //8.6改
        else
        flow_ram1_wren <= 1'b0;
end	
//**************************************************************

// integer    j;
// reg   [22:0]  data  ;

//**************************************************************
    reg[31:0] q_a_1_d1, q_a_2_d1 ;
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            q_a_1_d1 <= 32'd0 ;
            q_a_2_d1 <= 32'd0 ;
        end
        else if(step == 3'd2) begin
            q_a_1_d1 <= q_a_1 ;
            q_a_2_d1 <= q_a_2 ;
        end
        else begin
            q_a_1_d1 <= q_a_1_d1 ;
            q_a_2_d1 <= q_a_2_d1 ;
        end
    end
//**************************************************************

reg init_done;

always @ (posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
            wren_a_2 <= 1'b0 ;
            data_a_2 <= 32'd0;
            address_a<= 8'd0 ;
            loop     <= 9'd0 ;
            step     <= 3'd5 ;
            init_done <=  1'b0;

            ram1_cena <= 1'b0 ;
            ram2_cena <= 1'b0 ;
    	    // j<=0 ;
    	   // data<=23'd0 ;
        end
    else
        begin
            case(step)
            3'd5://RAM1清零 
            begin
                wren_a_2 <= 1'b1      ;
                data_a_2 <= 32'd0     ;
                address_a<= loop[7:0] ;

                ram1_cena <= 1'b1 ;
                ram2_cena <= 1'b1 ;
                
                if(loop == 9'h100)  
                    //等待在初始化完成（表1全部清零）
                begin
                    step <= 3'd0 ;
                    loop <=  9'd0;
                    init_done <= 1'b1;
                end              
                else begin
                    step <= 3'd5 ;
                    loop <=  loop + 9'd1;
                    init_done <= 1'b0;
                end
            end
            3'd0:
                begin
                    init_done <=  1'b0;
                    wren_a_2 <= 1'b0      ;
                    data_a_2 <= 32'd0     ;
                    address_a<= loop[7:0]      ;
                    // step     <= step+3'd1 ; //修改
					if ( (cpu_fread_write==1'b1 && cpu_faddr==loop[7:0]) || ( busy==1'b1 && operate_addr==loop[7:0]) ) begin
                        //看RAM2对应的地址是否在被操作（防止冲突）
                        step     <= step ;
                        ram1_cena <= 1'b0 ;
                        ram2_cena <= 1'b0 ;
                    end	
					else begin
						step     <= step+3'd1 ;
                        ram1_cena <= 1'b1 ;
                        ram2_cena <= 1'b1 ;
                    end
                end
            //等待数的读出
            3'd1:
                begin
                    step     <= step+3'd1 ;        
                 end
           3'd2:
                begin
                    step     <= step+3'd1 ;
                end
                
           3'd3:
                begin
                if(q_a_1_d1[15:0]==16'd0)
                    data_a_2<= 32'd0     ;  //最大令牌数为0则往RAM2里写0
                else if(q_a_2_d1[16]==1'b0)
                    data_a_2<= {15'd0,1'b1,q_a_1_d1[15:0]} ; //标志位为0则更新为最大数量
                else
                    begin
                        if( ({1'b0,q_a_2_d1[15:0]}+{1'd0,q_a_1_d1[31:16]}) >= {1'b0,q_a_1_d1[15:0]} )
                           begin
                            // data<= {1'b0,q_a_2_d1[21:0]}+{13'd0,q_a_1_d1[31:22]} ;
                            data_a_2 <= {15'd0,1'b1,q_a_1_d1[15:0]} ;
                           //   j<=5  ; //
                            end
                        else
                        begin
                            data_a_2 <= {15'd0,1'b1, (q_a_2_d1[15:0]+q_a_1_d1[31:16])} ;  
                        //    j<=3 ;	
                        end            
                    end
                 step <= step+3'd1 ;
                end
            3'd4:
                begin
                    if (busy==1'b1 && operate_addr==loop[7:0]  ) //等待RAM2不操作（和3'd5状态一样）
                        begin
                            wren_a_2 <= 1'b0      ;
                            step     <= step;
                            loop     <= loop ;
                        end
                    else
                        begin
                            wren_a_2 <= 1'b1      ;
                            step     <= 3'd0 ;
                            loop     <= loop+9'd1 ; //取下一个地址
                       end
                end
            default:
                begin
                    wren_a_2 <= 1'b0 ;
                    data_a_2 <= 32'd0;
                    address_a<= 8'd0 ;
                    loop     <= 9'd0 ;
                    step     <= 3'd0 ;
                end
    	endcase
    end
end


endmodule
















